package main

import "fmt"

type FnTy func(uint8, uint8) uint8

func mv(b int)uint8{
	return uint8(((b & 3) << 6) | (b << 3) | b)
}

const B_WID = 8
var A [][]uint8
var B [][]uint8

func iAB(){
for i := 0; i <= B_WID; i++ {
for j := 0; j <= B_WID; j++ {
	if i == j { continue; }
	A = append(A,[]uint8{mv(i),mv(j)})
}}


for i := 0; i <= B_WID; i++ {
for j := 0; j <= B_WID; j++ {
for k := 0; k <= B_WID; k++ {
	if i == j || j == k || i == k { continue; }
	B = append(B,[]uint8{mv(i),mv(j),mv(k)})
}}}
}

var FS = []FnTy{
	func(p, n uint8) uint8 { return p & n },
	func(p, n uint8) uint8 { return ^p & n },
	func(p, n uint8) uint8 { return p & ^n },
	func(p, n uint8) uint8 { return ^p & ^n },
	func(p, n uint8) uint8 { return p | n },
	func(p, n uint8) uint8 { return ^p | n },
	func(p, n uint8) uint8 { return p | ^n },
	func(p, n uint8) uint8 { return ^p | ^n },
	func(p, n uint8) uint8 { return p ^ n },
	func(p, n uint8) uint8 { return ^p ^ n },
	func(p, n uint8) uint8 { return p ^ ^n },
	func(p, n uint8) uint8 { return ^p ^ ^n },
	
}

const F_LEN = 12

var x, y, z, a, b, c uint8

/*
x:'0',y:'1',z:'_',a:'0',b:'1',c:'2'
(x,a) -> (x,a)
(x,b) -> (y,a)
(x,c) -> (x,b)
(y,a) -> (y,b)
(y,b) -> (x,c)
(y,c) -> (y,c)
(z,a) -> (z,a)
(z,b) -> (x,b)
(z,c) -> (z,c)
*/

func ck(f1, f2 FnTy, p1, n1, p2, n2 uint8) bool {
	// return (f1(p1, n1) == p2) && (f2(p1, n1) == n2)
	// 不清楚编译器是否懂得自动短路不进行f2的运算
	if(!f1(p1, n1) == p2) return false;
	if(!f2(p1, n1) == n2) return false;
	return true;
}

func main() {

	iAB();
	
	for _, p := range A {
	for _, n := range B {
		x = p[0]; y = p[1];
		// z = p[2]
		a = n[0]; b = n[1]; c = n[2];

		rd := [][]uint8{
			{x, a, x, a}, {x, b, y, a}, {x, c, x, b},
			{y, a, y, b}, {y, b, x, c}, {y, c, y, c},
			// {z, a, z, a}, {z, b, z, b}, {z, c, z, c},
		}

		for i := 0; i < len(FS); i++ {
		for j := 0; j < len(FS); j++ {
			if i == j {
				continue
			}
			/*
				if !(FS[i](x,a) == x && FS[j](x,a)== a) {continue}
				if !(FS[i](x,b) == y && FS[j](x,b)== a) {continue}
				if !(FS[i](x,c) == x && FS[j](x,c)== b) {continue}
				if !(FS[i](y,a) == y && FS[j](x,a)== b) {continue}
				if !(FS[i](y,b) == x && FS[j](x,b)== c) {continue}
				if !(FS[i](y,c) == y && FS[j](x,c)== c) {continue}
				if !(FS[i](z,a) == z && FS[j](z,a)== a) {continue}
				if !(FS[i](z,b) == z && FS[j](z,b)== b) {continue}
				if !(FS[i](z,c) == z && FS[j](z,c)== c) {continue}
			*/
			
			count := 0

			for k := 0; k < 6; k++ {
				if !ck(FS[i], FS[j], rd[k][0], rd[k][1], rd[k][2], rd[k][3]) { break }
				count++
			}

			if count == 6 {
				fmt.Printf("i:%d,j:%d,x:%b,y:%b,z:%b,a:%b,b:%b,c:%b\n", i, j, x, y, z, a, b, c)
			}
		}}
	}}
	// fmt.Printf("count:",count)

}

type Pair struct {
	x, y int
}

func extend()([]FnTy, []string){
	fs := make([]FnTy, len(FS), len(FS)+F_LEN*B_WID*6)
	copy(fs, FS)
	ftr := []string{
		"p & n" ,"^p & n" ,"p & ^n" ,"^p & ^n" ,"p | n" ,"^p | n" ,"p | ^n",
		"^p | ^n" ,"p ^ n" ,"^p ^ n" ,"p ^ ^n" ,"^p ^ ^n",
	}
	for i := 0; i < F_LEN; i++ {
		for j := 0; j < B_WID; j++ {
			/*
				要修复“闭包捕获循环变量”的问题，你需要确保在每次迭代中捕获i和j的当前值。
				这通常通过在循环体内部声明额外的局部变量来实现，
				这些变量在每次迭代时都会捕获i和j的当前值，
				然后这些局部变量会被用作闭包内部的引用。
			*/
			c_i := i
			c_j := j

			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](uint8(c_j)&p, n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](uint8(c_j)|p, n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](uint8(c_j)^p, n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](p, uint8(c_j)&n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](p, uint8(c_j)|n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](p, uint8(c_j)^n) })

			ftr = append(ftr, (fmt.Sprintf(" ( %d & p ) , %s ", c_j, ftr[c_i])))
			ftr = append(ftr, (fmt.Sprintf(" ( %d | p ) , %s ", c_j, ftr[c_i])))
			ftr = append(ftr, (fmt.Sprintf(" ( %d ^ p ) , %s ", c_j, ftr[c_i])))
			ftr = append(ftr, (fmt.Sprintf(" ( %d & n ) , %s ", c_j, ftr[c_i])))
			ftr = append(ftr, (fmt.Sprintf(" ( %d | n ) , %s ", c_j, ftr[c_i])))
			ftr = append(ftr, (fmt.Sprintf(" ( %d ^ n ) , %s ", c_j, ftr[c_i])))
		}
	}

	const L = len(fs)
	pair := make([]Pair, L)

extLoop:
	for i := 0; i < L; i++ {
	for j := 0; j < L; j++ {
		if i == j { continue }
		
		var flag = true
		for m := 0; m < B_WID; m++ {
		for n := 0; n < B_WID; n++ {
			flag = flag && (fs[i][m] == fs[j][n])
			if !flag { continue extLoop }
		}
		}

		pair = append(pair, Pair{i,j})
		fmt.Printf("All Logic same: (%d,%d) ", i, j)
	}
	}

	
	
	return fs,ftr
}


/**
 * 单纯的位运算是无法找到的。
 *    00 00 00
 *    00 01 01
 *    00 10 00
 *    01 00 00
 *    01 01 11
 *    01 10 10
 * 
 *  把每个数，按位拆开来分析
 *
 *   0 0 0 , 0 0 0       0 0 0 XA
 *   0 0 0 , 0 1 1       0 0 1 XA
 *   0 1 0 , 0 0 0 ----\ 0 1 0 XB
 *   0 0 0 , 1 0 0 ----/ 0 1 1 XB
 *   0 0 1 , 1 1 1		 1 0 0
 *   0 1 1 , 1 0 0		 1 1 1
 */

func main2() {
	fs := FS[:]
	// ftr := []string{
	// 	"p & n" ,"^p & n" ,"p & ^n" ,"^p & ^n" ,"p | n" ,"^p | n" ,"p | ^n",
	// 	"^p | ^n" ,"p ^ n" ,"^p ^ n" ,"p ^ ^n" ,"^p ^ ^n",
	// }

	for i := 0; i < F_LEN; i++ {
		for j := 0; j < B_WID; j++ {
			/*
				要修复“闭包捕获循环变量”的问题，你需要确保在每次迭代中捕获i和j的当前值。
				这通常通过在循环体内部声明额外的局部变量来实现，
				这些变量在每次迭代时都会捕获i和j的当前值，
				然后这些局部变量会被用作闭包内部的引用。
			*/
			c_i := i
			c_j := j

			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](uint8(c_j)&p, n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](uint8(c_j)|p, n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](uint8(c_j)^p, n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](p, uint8(c_j)&n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](p, uint8(c_j)|n) })
			fs = append(fs, func(p, n uint8) uint8 { return FS[c_i](p, uint8(c_j)^n) })

			// ftr = append(ftr, (fmt.Sprintf(" ( %d & p ) , %s ", c_j, ftr[c_i])))
			// ftr = append(ftr, (fmt.Sprintf(" ( %d | p ) , %s ", c_j, ftr[c_i])))
			// ftr = append(ftr, (fmt.Sprintf(" ( %d ^ p ) , %s ", c_j, ftr[c_i])))
			// ftr = append(ftr, (fmt.Sprintf(" ( %d & n ) , %s ", c_j, ftr[c_i])))
			// ftr = append(ftr, (fmt.Sprintf(" ( %d | n ) , %s ", c_j, ftr[c_i])))
			// ftr = append(ftr, (fmt.Sprintf(" ( %d ^ n ) , %s ", c_j, ftr[c_i])))
		}
	}

	gB := []struct {
		t, b, r uint8
	}{
		{t: 0, b: 0, r: 0}, 
		{t: 0, b: 1, r: 0}, 
		{t: 0, b: 2, r: 1},
		{t: 1, b: 0, r: 1},
		{t: 1, b: 1, r: 2},
		{t: 1, b: 2, r: 2},
	}

outLoop:
	for i, f := range fs {
		for _, n := range gB {
			if f(n.t, n.b) != n.r {
				// fmt.Println(" != ")
				continue outLoop
			}
		}
		fmt.Printf("#%3d fs:%s  \n", i, ftr[i])
	}

}